﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SongSharp.Domain.Objects;


namespace SongSharp.Domain.Suggesting.VaryVogueValue
{
    public enum SpectrumElement
    {
        Undefined = 0,

        Worst = 1,
        Worse = 2,
        Bad = 3,
        Balanced = 4,
        Good = 5,
        Well = 6,
        Best = 7,
    }

    public class ChanceValue
    {
        public enum VVVType
        {
            Undefined = 0,

            Vital_Played_Skipped_Ratio = 1,
            Vista_Heat_Played_Hours = 2,
            Vista_Heat_Skipped_Hours = 3,
            Vista_Heat_Added_Days = 4,

            JoinedEvidence = 5
        }

        public static readonly ChanceValue MAX = new ChanceValue(1.0, 1.0, 1.0, SpectrumElement.Best);
        public static readonly ChanceValue MIN = new ChanceValue(0.0, 0.0, 1.0, SpectrumElement.Worst);
        public static readonly ChanceValue UNDEFINED = new ChanceValue(double.NaN, double.NaN, double.NaN, 
            SpectrumElement.Undefined) { ValueType = VVVType.Undefined };

        public double Value { get; set; }
        public double OriginalValue { get; set; }
        public double DegreeOfBelief { get; set; }
        public SpectrumElement SpectrumElement { get; set; }
        public VVVType ValueType { get; set; }
        
        public ChanceValue(double value, double originalValue, double degreeOfBelief, SpectrumElement spec)
        {
            Value = value;
            OriginalValue = originalValue;
            DegreeOfBelief = degreeOfBelief;
            SpectrumElement = spec;
        }

        #region Overloaded operators and methods
        public override string ToString()
        {
            return "x = " + Value.ToString() + " [" + SpectrumElement.ToString() 
                + "], DoB = " + DegreeOfBelief + ", oValue = " + OriginalValue;
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            try
            {
                return ((ChanceValue)obj) == this;
            }
            catch (InvalidCastException)
            {
                return false;
            }
        }

        public static bool operator ==(ChanceValue v1, ChanceValue v2)
        {
            return v1.Value == v2.Value && v1.DegreeOfBelief == v2.DegreeOfBelief;
        }

        public static bool operator !=(ChanceValue v1, ChanceValue v2)
        {
            return v1.Value != v2.Value || v1.DegreeOfBelief != v2.DegreeOfBelief;
        }

        public static ChanceValue operator +(ChanceValue w1, ChanceValue w2)
        {
            return new ChanceValue(
                (w1.DegreeOfBelief * w2.DegreeOfBelief * w1.Value * w2.Value)
                + ((1-w1.DegreeOfBelief) * w2.DegreeOfBelief * w2.Value)
                + ((1-w2.DegreeOfBelief) * w1.DegreeOfBelief * w1.Value), 
                double.NaN, 
                1.0, 
                SpectrumElement.Undefined) 
                { 
                    ValueType = VVVType.JoinedEvidence 
                };
        }
        #endregion
    }
}
